package com.fuluwa.interfaces.bank.facade;

import java.math.BigDecimal;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.fuluwa.domain.bank.model.Account;
import com.fuluwa.domain.bank.repository.AccountRepository;
import com.fuluwa.domain.security.model.User;
import com.fuluwa.domain.security.repository.UserRepository;
import com.fuluwa.domain.vendor.model.RequestLog;
import com.fuluwa.domain.vendor.model.ResponseLog;
import com.fuluwa.domain.vendor.model.Vendor;
import com.fuluwa.domain.vendor.repository.RequestLogRepository;
import com.fuluwa.domain.vendor.service.VendorService;
import com.fuluwa.infra.exception.PersistenceException;

@Component
public class BankServiceFacadeImpl implements BankServiceFacade {
	@Autowired
	VendorService vendorService;

	@Autowired
	UserRepository userRepository;
	@Autowired
	AccountRepository accountRepository;
	
	@Autowired
	RequestLogRepository requestLogRepository;

	@Override
	public String getAccountNo(String loginName) {
		User user = userRepository.findByLoginName(loginName);
		List<Account> accounts = accountRepository.findByUser(user);
		for (Account account : accounts) {
			if (account.isCashAccount()) {
				return account.getAccountNo();
			}
		}
		return null;
	}

	@Override
	@Transactional
	public ResponseDTO prepareDeposit(String accountNo, BigDecimal amount, Vendor vendor, String desc)
			throws PersistenceException {
		RequestLog reqLog = vendorService.prepareDeposit(accountNo, amount, vendor, desc);
		ResponseDTO ret = new ResponseDTO();
		ret.setRequestContent(reqLog.getRequestContent());
		ret.setRequestURL(reqLog.getRequestURL());
		ret.setReferenceNo(reqLog.getReferenceNo());
		return ret;
	}

	@Override
	@Transactional
	public void doDeposit(String referenceNo, String responseContent, Vendor vendor) throws PersistenceException {
		ResponseLog respLog = vendorService.saveResponseLog(referenceNo, responseContent, vendor);
		changeReqStatus(referenceNo);
		try {
			vendorService.doDeposit(referenceNo);
		} catch (Exception e) {
			throw new PersistenceException("do deposit error:"+e.getMessage(), e);
		}
		
	}

	@Transactional(propagation=Propagation.REQUIRES_NEW)
	private void changeReqStatus(String referenceNo) throws PersistenceException {
		RequestLog reqLog = requestLogRepository.findByReferenceNo(referenceNo);
		reqLog.changeToReply();
	}

	@Override
	@Transactional
	public ResponseDTO prepareWithdrawl(String accountNo, BigDecimal amount, Vendor vendor, String desc)
			throws PersistenceException {
		RequestLog reqLog = vendorService.prepareWithdrawl(accountNo, amount, vendor, desc);
		ResponseDTO ret = new ResponseDTO();
		ret.setRequestContent(reqLog.getRequestContent());
		ret.setRequestURL(reqLog.getRequestURL());
		ret.setReferenceNo(reqLog.getReferenceNo());
		return ret;
	}

	@Override
	@Transactional
	public void doWithdrawl(String referenceNo, String responseContent, Vendor vendor) throws PersistenceException {
		ResponseLog respLog = vendorService.saveResponseLog(referenceNo, responseContent, vendor);
		changeReqStatus(referenceNo);
		try {  
			vendorService.doWithdrawl(referenceNo);
		} catch (Exception e) {
			throw new PersistenceException("do withdrawl error:"+e.getMessage(), e);
		}
		
	}
}
